package org.javarosa.ccptz.midlet;

/**
* Title: MIDPLogger
* Description: Redirect MIDlet for S60 devices
* Copyright: Copyright (c) 2008
* Company: Nokia
*
* @author Nokia
* @version 1.0
*/
 
import java.io.IOException;
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;
import javax.microedition.lcdui.Command;
import javax.microedition.lcdui.CommandListener;
import javax.microedition.lcdui.Display;
import javax.microedition.lcdui.TextBox;
import javax.microedition.lcdui.TextField;
import javax.microedition.lcdui.Displayable;
import javax.microedition.lcdui.Alert;
import javax.microedition.lcdui.AlertType;
import javax.microedition.io.Connector;
import javax.microedition.io.InputConnection;
import java.io.InputStream;
import java.io.OutputStream;
import javax.microedition.io.file.FileConnection;
 
public class MIDPLogger extends MIDlet implements Runnable, CommandListener {
    private static final int READ_BUFFER = 256;
    private static final String URL_S60_3_2 = "redirect://test";
    private static final String URL_S60_3_1 = "redirect://";
    private boolean isAppStarted = false;
    private boolean keepLogging = true;
    private Command clearLogger;
    private Command saveLogger;
    private Command exitLogger;
    private TextBox logTextBox;
    private InputStream inputStream;
    private WriteData writeData;
    private Alert messageAlert;
    private Display display;
    private boolean s60_3_2 = true;
 
    /**
    * startApp
    *
    * @throws MIDletStateChangeException
    */
    protected void startApp() throws MIDletStateChangeException {
        if (!isAppStarted) {
            Thread t = new Thread(this);
            t.start();
            isAppStarted = true;
        }
    }
 
    /**
    * pauseApp Method is called when the midlet is paused
    */
    protected void pauseApp() {
    }
 
    /**
    * destroyApp
    *
    * @param b 
    * @throws MIDletStateChangeException
    */
    protected void destroyApp(boolean b)throws MIDletStateChangeException {
    }
 
    /**
     * Initializes the MIDlet UI: creates and adds the commands and sets the 
     * logTextBox as current Displayable.
     */
    private void initUI() {
        display = Display.getDisplay(this);
        logTextBox = new TextBox("MIDPLogger", "", 10000, TextField.ANY);
        saveLogger = new Command("Save in file", Command.SCREEN, 1);
        logTextBox.addCommand(saveLogger);
        clearLogger = new Command("Clear", Command.CANCEL, 1);
        logTextBox.addCommand(clearLogger);
        exitLogger = new Command("Exit", Command.EXIT, 1);
        logTextBox.addCommand(exitLogger);
        logTextBox.setCommandListener(this);
        display.setCurrent(logTextBox);
        writeData = new WriteData();
    }
 
    /**
     * Creates the input stream and also checks, if the device is S60 3rd Ed. FP2
     * device or newer. Note: "java_build_version" information was added to the
     * "microedition.platform" property value in S60 3rd Ed. FP2 devices.
     */
    private void createInputStream() {
        String platform = System.getProperty("microedition.platform");
        if(platform.indexOf("java_build_version") > 0){
            s60_3_2 = true;     // S60 3.2 or higher
        }
        else {
            s60_3_2 = false;    // S60 3.1 or older version
        }
        createRedirectInputStreamCon();
    }
 
    /** 
     * This method selects the url to be used and informs user about the
     * S60 platform release of the device.
     */
    private void createRedirectInputStreamCon() {
        try {
            if (s60_3_2) {
                InputConnection inputConnection = (InputConnection)
                    Connector.open(URL_S60_3_2, Connector.READ);
                inputStream = inputConnection.openInputStream();
                logTextBox.insert("Platform S60 3rd Ed. FP2 or newer.\n",
                    logTextBox.size());
            }
            else { 
                //inputStream = Connector.openInputStream(URL_S60_3_1);
                InputConnection inputConnection = (InputConnection)
                    Connector.open(URL_S60_3_1, Connector.READ);
                inputStream = inputConnection.openInputStream();
                logTextBox.insert("Platform S60 3rd Ed. FP1 or older.\n",
                    logTextBox.size());
            }
        } catch (IOException ioe) {
            logTextBox.insert("IOException: " + ioe.getMessage() + "\n",
                logTextBox.size());
        }
    }
 
    public void commandAction(Command command, Displayable displayable) {
        if (command == clearLogger) {
            logTextBox.setString("");
        }
        else if (command == saveLogger) {
            Thread thread = new Thread(writeData);
            thread.start();
        }
        else if (command == exitLogger) {
            keepLogging = false;
            this.notifyDestroyed();
        }
    }
 
    public void run() {
        initUI();
        createInputStream();
        readData();
    }
 
    /** 
     * Reads data from the input stream and displays it
     */
    private void readData() {
        if(inputStream == null){
            showAlert("Error", "The url redirect:// is not supported", AlertType.ERROR);
            return;
        }
        readDataAndDisplay();
    }
    
    /**
     * Reads data MIDlet system out and error stream and shows it to user
     */
    private void readDataAndDisplay() {
        // read data from stream and display it in text box
        byte[] data = new byte[READ_BUFFER];
        int len = -1;
        while (keepLogging) {
            try { // if there is no data this will block
                len = inputStream.read(data);
            } catch (IOException ioe) {
                logTextBox.insert("IOException: " + ioe.getMessage() + "\n",
                    logTextBox.size());
            }
            if(len > 0){
                String str = new String(data, 0, len);
                int maxSize = logTextBox.getMaxSize();
                if (logTextBox.size() >= maxSize) {
                    logTextBox.setMaxSize(maxSize + READ_BUFFER * 10);
                }
                logTextBox.insert(str + "\n", logTextBox.size());
            }
//            System.out.println("Test Output");
//            System.err.println("Test Error");
        } 
    }
 
 
    private void showAlert(String title, String message, AlertType alertType){
        if(null == messageAlert){
            messageAlert = new Alert(message);
        }
        messageAlert.setTitle(title);
        messageAlert.setString(message);
        messageAlert.setType(alertType);
 
        if(alertType == AlertType.ERROR){
            messageAlert.setTimeout(Alert.FOREVER);
        }
        else{
            messageAlert.setTimeout(3000);
        }
        display.setCurrent(messageAlert);
    }
 
    class WriteData implements Runnable {
        WriteData() {}
 
        public void run() {
            saveData();
        }
 
        /**
         * Saves data to file system
         */ 
        private void saveData() {
            try {
                String data = logTextBox.getString();
                String fname = "file:///C:/Data/Images/log.txt";
                FileConnection fileOutputConnection = (FileConnection)
                    Connector.open(fname);
                // Create file specified in url if it does not exist
                if (!fileOutputConnection.exists()) {
                    // create the directory if it does not exist
                    String path = "file://" + fileOutputConnection.getPath();
                    FileConnection fc = (FileConnection) Connector.open(path);
                    if (!fc.exists()) {
                        fc.mkdir();
                    }
                    fc.close();
                    // create the file if it doesn't exist
                    fileOutputConnection.create();
                }
                OutputStream outputStream = fileOutputConnection.openOutputStream();
                outputStream.write(data.getBytes());
                outputStream.close();
                fileOutputConnection.close();
                logTextBox.setString("Log saved to " + fname.substring(8));
            } catch (IOException ioe) {
                logTextBox.insert("IOException: " + ioe.getMessage() + "\n",
                    logTextBox.size());
            }
        }
    }
}